package com.lxy.新特性.lambda.练习;

import com.lxy.mybatis.pojo.User.Emp;
import com.lxy.mybatis.pojo.User.EnumStatus;
import com.lxy.新特性.lambda.练习.函数式接口.I2Lambda;
import com.lxy.新特性.lambda.练习.函数式接口.ILambda;
import org.junit.Test;

import java.util.*;
import java.util.function.*;

public class LambdaExam {
    //初始化员工数据
    List<Emp> tmp = Arrays.asList(
            new Emp(1,"lxy",2,'女',"123@qq.com", EnumStatus.CLOSE),
            new Emp(2,"lili",21,'女',"456@qq.com", EnumStatus.OPEN),
            new Emp(3,"lucy",21,'女',"789@qq.com", EnumStatus.CLOSE),
            new Emp(4,"pite",41,'男',"101@qq.com", EnumStatus.OPEN),
            new Emp(4,"pite",41,'男',"101@qq.com",EnumStatus.FREE),
            new Emp(4,"pite",41,'男',"101@qq.com",EnumStatus.FREE),
            new Emp(4,"pite",41,'男',"101@qq.com",EnumStatus.OPEN),
            new Emp(8,"qiqi",1,'女',"110@qq.com",EnumStatus.CLOSE)
    ) ;
    @Test
    public void testLambda() {
        //定制排序
        Collections.sort(tmp,(e1,e2) -> {
            Integer cmp = Integer.compare(e1.getAge(), e2.getAge());
            Integer cmpName = e1.getEmpName().compareTo(e2.getEmpName());
            if(cmp != 0){
                return cmp;
            } else{
                return cmpName;
            }
        });

        tmp.forEach(System.out::println);
    }

    @Test
    public void testLambda2() {
        //通过lambda函数式接口指定数据要处理的运算
        String s1 = IFun("abcdefg", (s) -> s.toLowerCase().substring(2, 4));
        System.out.println(s1);
    }

    //将函数式接口作为参数传递
    public String IFun(String s, ILambda iLambda){
        return iLambda.getValue(s);
    }

    @Test
    public void testLambda3() {
        //简化方法
        long add = sum(1, 2, (a, b) -> (a + b));
        System.out.println(add);

        long sum = sum(1, 2, (a, b) -> (a * b));
        System.out.println(sum);
    }

    //泛型接口需要被实体化
    public long sum(long a, long b, I2Lambda<Long,Long> i2Lambda){
        return i2Lambda.js(a,b);
    }

    /**
     * 内置四大核心函数式接口
     * 1、void accept(T)消费型接口
     * 2、R get()供给型接口
     * 3、R apply(T)函数型接口
     * 4、Boolean test(T)断言型接口
     * */

    @Test
    public void testfun1() {
        funTest1(1200,(a)-> System.out.println("a:"+a));
    }
    public void funTest1(double m, Consumer<Double> consumer) {
        consumer.accept(m);
    }

    @Test
    public void testfun2() {
        //先得到(Math.random() * 100) Double的数据，在转化为int
        List num = getNum(10, () -> (int) (Math.random() * 100));
        num.forEach(System.out::println);
    }
    //参数指定个数并放入集合
    public List getNum(int num, Supplier<Integer> nums){
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            list.add(nums.get());
        }
        return list;
    }

    @Test
    public void testfun3() {
        List<String> list = Arrays.asList("abc","abcd","abcde","def");
        List<String> target = target(list, (s) -> s.length() > 3);
        target.forEach(System.out::println);
    }
    //【过滤】出【用户名集合】>3
    public List<String> target(List<String> score, Predicate<String> pre){
        List<String> list = new ArrayList<>();
        for (int i = 0; i < score.size(); i++) {
            if(pre.test(score.get(i))){
                list.add(score.get(i));
            }
        }
        return list;
    }

    @Test
    public void testfun4() {
        //方法引用；注：方法引用方法和函数式抽象方法一致
        Consumer<String> consumer = System.out::println;
        consumer.accept("abc");

        Emp emp = new Emp();
        //对象::方法名
        Supplier<String> getEmpName = emp::getEmpName;
        Supplier<Integer> getAge = emp::getAge;
        String s = getEmpName.get();
        Integer i = getAge.get();
        System.out.println(s+i);
    }

    @Test
    public void testfun5() {
        //lambda体内的方法有合适的方法引用
        //lambda表示
        Comparator<Integer> comparator = (x,y) -> Integer.compare(x, y);
        //类::静态方法
        Comparator<Integer> comparator1 = Integer::compare;

        BiPredicate<String,String> biPredicate = (x,y) -> x.equals(y);
        //类::实例方法；注：x是y的调用这，y是x的参数接受
        BiPredicate<String,String> biPredicate1 = String::equals;
    }

    @Test
    public void testfun6() {
        Supplier<Emp> res = ()-> new Emp();
        //构造器引用方式(无参构造)
        Supplier<Emp> res1 = Emp::new;
        Emp emp = res1.get();
        System.out.println(emp);
        //注：使用构造器引用方式的参数列表要和函数式接口中抽象方法的参数列表保持一致
        Function<Integer, Emp> fun = (x) -> new Emp();
        Function<Integer, Emp> fun1 = Emp::new;
    }

    @Test
    public void testfun7() {
        //初始化数据长度
        Function<Integer, Integer[]> fun = (x) -> new Integer[x];
        Function<Integer, Integer[]> fun1 =Integer[]::new ;
        Integer[] apply = fun1.apply(2);
        System.out.println(apply.length);

        //集合是一个对象
        Function<Integer,ArrayList<Integer>> fun2=ArrayList<Integer>::new;
    }
}
